﻿package com.eitb.programas.streamingWeb{
	import flash.display.*;
	import flash.events.*;
	import flash.text.*;
	import flash.media.*;
	import flash.utils.*;
	import flash.net.*;
	import flash.geom.*;

	import com.akamai.net.*;
	import org.openvideoplayer.events.*;

	import com.eitb.programas.streamingTest.literales.*;
	import com.eitb.programas.streamingTest.properties.*;
	import com.eitb.programas.streamingTest.botones.*;
	import com.eitb.literales.*;
	import com.eitb.bitmaps.*;
	import com.eitb.nielsen.*;
	import com.eitb.rutas.*;
	import com.eitb.cargadores.*;
	import com.eitb.formaters.*;
	import com.eitb.botones.*;
	import com.eitb.events.*;
	import com.eitb.imagenes.*;
	import com.eitb.reproductores.*;

	public class ModeloStreaming implements IControladorStreaming,IControladorCargador {

		private var vStreaming:IVistaStreaming;
		private var vCargador:IVistaCargador;
		private var vVolume:IVistaScrollBar;
		private var vTimeline:IVistaScrollBar;
		private var vMaximize:IVistaBoton;
		private var vStop:IVistaBoton;
		private var vPause:IVistaBoton;
		private var vPlay:IVistaBoton;
		private var vPortada:IVistaGrafico;
		private var vBackground:IVistaGrafico;
		private var vZonaControl:IVistaGrafico;
		private var vVideo:IVistaVideo;

		// parametros
		private var properties:Object;
		private var hostname:String;
		private var filename:String;
		private var imagen:String;
		private var streaming:Boolean;// si es falso reproduce streaming de flv
		private var autoplay:Boolean;
		//Marcado de Nielsen
		private var nielsenVideoCall:NielsenVideoCall;
		private var canal:String;

		private var connection:NetConnection;
		private var stream:AkamaiEnhancedNetStream;

		private var idioma:int;
		private var literales:ILiterales;
		private var literalesCargador:ILiterales;
		private var literalesControles:ILiterales;

		private var duration:Number;
		private var portadaCropedRectangle:Rectangle;
		private var state:String;

		public function ModeloStreaming():void {
			this.duration=0;
			this.portadaCropedRectangle = new Rectangle();
		}
		public function initNielsen(canal:String):void {
			this.nielsenVideoCall=new NielsenVideoCall("STREAMING",canal);
		}
		public function initVistaStreaming(vStreaming:IVistaStreaming):void {
			this.vStreaming=vStreaming;
		}
		public function initIdioma(idioma:int):void {
			this.idioma=idioma;
			this.literales=new StreamingLiterales(idioma);
		}
		public function initFormato(properties:Object):void {
			this.properties=properties;
		}
		public function initHostname(hostname:String):void {
			this.hostname=hostname;
			if (-1 != this.hostname.search("live")) {
				this.streaming = true;
			} else {
				this.streaming = false;
			}
		}
		public function initFilename(filename:String):void {
			this.filename=filename;
		}
		public function initCanal(canal:String):void {
			this.canal=canal;
		}
		public function initAutoplay(autoplay:String):void {
			if (null!=autoplay&&""!=autoplay) {
				this.autoplay=true;
			} else {
				this.autoplay=false;
			}
		}
		public function initAkamaiConnection():void {
			var sCon:String;
			this.connection=new NetConnection();
			this.connection.client=this;
//			this.connection.addEventListener(AsyncErrorEvent.ASYNC_ERROR, ayncErrorHandler);
			this.connection.addEventListener(NetStatusEvent.NET_STATUS,netStatusHandler);

			sCon="rtmp://".concat(this.hostname).concat("/").concat(this.filename);
			trace(sCon);
			this.connection.connect(sCon ,true,true,4,true);
			//this.connection.connect(this.hostname,true,true,4,true);
			//this.connection.connect("rtmp://cp70268.live.edgefcs.net/live/eitb-CanalVasco@5519",true,true,4,true);
			//this.connection.connect("http://www.eitb.com/multimedia/videos/2009/10/14/185007/LaHuerfana_20091014_091303.flv",true,true,4,true);

			//protocol:[//host][:port]/appname[/instanceName]
			// connect(AkamaiHostname:String, detectBandwidth:Boolean,createNetStream:Boolean, maxBufferLength:Number,useFastStartBuffer:Boolean, isLive:Boolean, port:String,protocol:String)
		}
// CLIENTE DE LA CONEXION
		public function onBWDone( kbitDown:Number, deltaDown:Number, deltaTime:Number, latency:Number):void {
			trace("onBWDone: kbitDown = " + kbitDown + ", deltaDown= " + deltaDown + ", deltaTime = " + deltaTime + ", latency = " + latency);
			trace("Son kbytes->" + (kbitDown * 0.12207));
			var tot:Number=kbitDown*0.12207;
		}
		public function onBWCheck(res:Object = null):int {
			return 0;
		}

		public function onFCSubscribe(info:Object):void {
			trace("suscrito");
		}
		public function onFCUnsubscribe(info:Object):void {
			trace("desconectado");
		}
// CLIENTE DE LA CONEXION		

		public function initVistaPortada(portada:Grafico, url:String):void {
			var loader:Loader;
			loader=new Loader();

			this.vPortada=portada;
			this.vStreaming.addChild(portada);

			loader.contentLoaderInfo.addEventListener(Event.COMPLETE, this.onCargaImagenPortada);
			try {
				loader.load(new Rutas().getRutaImagen(url));
			} catch (error:Error) {
				trace("Unable to load requested document.");
			}
		}

		private function onCargaImagenPortada(event:Event):void {
			var pos:Rectangle;
			var bitmap:DisplayObject;
			var loader:Loader=Loader(event.target.loader);
			bitmap=loader.content;

			this.portadaCropedRectangle = new ImagenAjuste().getImagenCrop(new Point(bitmap.width, bitmap.height), new Rectangle(this.properties.PORTADA.x,this.properties.PORTADA.y,this.properties.PORTADA.width, this.properties.PORTADA.height));

			this.vPortada.addChild(bitmap);
			this.vPortada.move(this.portadaCropedRectangle.x, this.portadaCropedRectangle.y);
			this.vPortada.setSize(this.portadaCropedRectangle.width, this.portadaCropedRectangle.height);

			this.vStreaming.fitScreen();
		}

		public function initVistaVideo(video:SimpleVideo):void {
			this.vVideo=video;
			this.vStreaming.addChild(video);
		}

		// CONTROLADOR CARGADOR
		public function initVistaCargador(cargador:*):void {
			this.vCargador=cargador;
			this.vStreaming.addChild(cargador);
		}
		public function initLiterales(literales:ILiterales):void {
			this.literales=literales;
		}
		public function initLiteralesCargador(literales:ILiterales):void {
			this.literalesCargador=literales;
		}
		public function initLiteralesControles(literales:ILiterales):void {
			this.literalesControles=literales;
		}
		// CONTROLADOR CARGADOR
		// CONTROLADOR MAXIMIZAR
		public function initVistaMaximize(maximize:BotonMaximize):void {
			this.vMaximize=maximize;
			this.vStreaming.addChild(maximize);
			maximize.setText(this.literalesControles.getLiteral(ControlesLiterales.MAXIMIZE).toUpperCase());

			maximize.addEventListener(MouseEvent.CLICK, this.onMaximizeClick);
			maximize.addEventListener(MouseEvent.MOUSE_OVER, this.onZonaControlOver);
			maximize.addEventListener(MouseEvent.MOUSE_OUT, this.onZonaControlOut);
		}
		// MAXIMIZAR
		// PLAY
		public function initVistaPlay(play:BotonPlay):void {
			this.vPlay=play;
			this.vStreaming.addChild(play);
			play.setText(this.literalesControles.getLiteral(ControlesLiterales.PLAY).toUpperCase());

			play.addEventListener(MouseEvent.CLICK, this.onPlayClick);
			play.addEventListener(MouseEvent.MOUSE_OVER, this.onZonaControlOver);
			play.addEventListener(MouseEvent.MOUSE_OUT, this.onZonaControlOut);
		}
		// PLAY
		// PAUSE
		public function initVistaPause(pause:BotonPause):void {
			this.vPause=pause;
			this.vStreaming.addChild(pause);
			pause.setText(this.literalesControles.getLiteral(ControlesLiterales.PAUSE).toUpperCase());

			pause.addEventListener(MouseEvent.CLICK, this.onPauseClick);
			pause.addEventListener(MouseEvent.MOUSE_OVER, this.onZonaControlOver);
			pause.addEventListener(MouseEvent.MOUSE_OUT, this.onZonaControlOut);
		}
		// PAUSE
		// ZONACONTROL
		public function initVistaZonaControl(zonaControl:Grafico):void {
			this.vZonaControl=zonaControl;
			this.vStreaming.addChild(zonaControl);

			zonaControl.addEventListener(MouseEvent.MOUSE_OVER, this.onZonaControlOver);
			zonaControl.addEventListener(MouseEvent.MOUSE_OUT, this.onZonaControlOut);
		}
		// ZONACONTROL
		// BACKGROUND
		public function initVistaBackground(background:Grafico):void {
			this.vBackground=background;
			this.vStreaming.addChild(background);

			background.addEventListener(MouseEvent.MOUSE_OVER, this.onZonaControlOver);
			background.addEventListener(MouseEvent.MOUSE_OUT, this.onZonaControlOut);
		}
		// BACKGROUND
		// STOP
		public function initVistaStop(stop:BotonStop):void {
			this.vStop=stop;
			this.vStreaming.addChild(stop);
			stop.setText(this.literalesControles.getLiteral(ControlesLiterales.STOP).toUpperCase());
			
			stop.addEventListener(MouseEvent.CLICK, this.onStopClick);
			stop.addEventListener(MouseEvent.MOUSE_OVER, this.onZonaControlOver);
			stop.addEventListener(MouseEvent.MOUSE_OUT, this.onZonaControlOut);
		}
		// STOP
		// CONTROLADOR VOLUMEN
		public function initVistaVolumen(volume:VolumeBar):void {
			this.vVolume=volume;
			this.vStreaming.addChild(volume);
			volume.setText(this.literalesControles.getLiteral(ControlesLiterales.VOLUMEN));
			
			// cuando se mueva el scroll se cambia el volumen
			volume.addEventListener(ScrollEvent.POINT_SELECTED, this.onVolumeClick);
			// cuando entra o sale de la barra controla el panel (aparece o desaparece)
			volume.addEventListener(MouseEvent.MOUSE_OVER, this.onZonaControlOver);
			volume.addEventListener(MouseEvent.MOUSE_OUT, this.onZonaControlOut);
			// cuando se mueva el raton por la pantalla comprueba si debe cambiar las barras de volumen
			this.vStreaming.addEventListener(MouseEvent.MOUSE_MOVE, volume.mouseMove);
			this.vStreaming.addEventListener(MouseEvent.MOUSE_UP, volume.mouseUp);
		}
		// CONTROLADOR VOLUMEN
		// CONTROLADOR TIMELINE
		public function initVistaTimeline(timeline:TimelineBar):void {
			this.vTimeline=timeline;

			this.vStreaming.addChild(timeline);

			timeline.addEventListener(ScrollEvent.POINT_SELECTED, this.onTimelineClick);
			timeline.addEventListener(MouseEvent.MOUSE_OVER, this.onZonaControlOver);
			timeline.addEventListener(MouseEvent.MOUSE_OUT, this.onZonaControlOut);

			this.vStreaming.addEventListener(MouseEvent.MOUSE_MOVE, timeline.mouseMove);
			this.vStreaming.addEventListener(MouseEvent.MOUSE_UP, timeline.mouseUp);
		}
		// CONTROLADOR TIMELINE
		// CONTROLADOR STREAMING
		public function onPlayClick(e:MouseEvent):void {
			//AkamaiEnhancedNetStream.STATE_BUFFERING
			//AkamaiEnhancedNetStream.STATE_ENDED
			//AkamaiEnhancedNetStream.STATE_FAILED
			//AkamaiEnhancedNetStream.STATE_PLAYING
			//AkamaiEnhancedNetStream.STATE_SEEKING
			//AkamaiEnhancedNetStream.STATE_STOPPED
			//AkamaiEnhancedNetStream.STATE_WAITING
			//AkamaiEnhancedNetStream.STATE_PAUSED
			trace(this.stream.state);
			switch (this.stream.state) {
				case AkamaiEnhancedNetStream.STATE_PAUSED :
					this.stream.resume();
					break;
				default :
					this.stream.play(this.filename);
					break;
			}
			this.setControlsView(AkamaiEnhancedNetStream.STATE_PLAYING);
		}
		public function onResumeClick(e:MouseEvent):void {
			this.stream.resume();
			this.setControlsView(AkamaiEnhancedNetStream.STATE_PAUSED);
		}

		public function onZonaControlOver(e:MouseEvent):void {
			this.setControlsView(this.state);
		}
		public function onZonaControlOut(e:MouseEvent):void {
			this.hideControls();
		}

		public function onStopClick(e:MouseEvent):void {
			this.stream.close();
			this.setControlsView(AkamaiEnhancedNetStream.STATE_STOPPED);
		}
		public function onPauseClick(e:MouseEvent):void {
			this.stream.pause();
			this.setControlsView(AkamaiEnhancedNetStream.STATE_PAUSED);
		}

		private function setControlsView(estado:String):void {
			switch (estado) {
				case AkamaiEnhancedNetStream.STATE_STOPPED :
					this.setStopView();
					break;
				case AkamaiEnhancedNetStream.STATE_PLAYING :
					this.setPlayView();
					break;
				case AkamaiEnhancedNetStream.STATE_PAUSED :
					this.setPauseView();
					break;
			}
			this.state=estado;
		}

		private function setStopView():void {
			this.vStop.setVisible(false);
			this.vPause.setVisible(false);
			this.vCargador.setVisible(false);

			this.vBackground.setVisible(true);
			this.vMaximize.setVisible(true);
			this.vVolume.setVisible(true);
			this.vPlay.setVisible(true);

			this.vTimeline.setVisible(true && !this.streaming);
		}
		private function setPlayView():void {
			this.vPlay.setVisible(false);

			this.vStop.setVisible(true);
			this.vBackground.setVisible(true);
			this.vMaximize.setVisible(true);
			this.vVolume.setVisible(true);
			this.vCargador.setVisible(!(this.stream.currentFPS != 0));

			this.vPause.setVisible(true && !this.streaming);
			this.vTimeline.setVisible(true  && !this.streaming);
		}
		private function setPauseView():void {
			this.vPause.setVisible(false);
			this.vCargador.setVisible(false);

			this.vPlay.setVisible(true);
			this.vStop.setVisible(true);
			this.vBackground.setVisible(true);
			this.vMaximize.setVisible(true);
			this.vVolume.setVisible(true);

			this.vTimeline.setVisible(true  && !this.streaming);
		}

		private function hideControls():void {
			this.vPlay.setVisible(false);
			this.vStop.setVisible(false);
			this.vBackground.setVisible(false);
			this.vMaximize.setVisible(false);
			this.vVolume.setVisible(false);

			this.vPause.setVisible(false);
			this.vTimeline.setVisible(false);
		}

		public function onMaximizeClick(e:MouseEvent):void {
			if (StageDisplayState.FULL_SCREEN==this.vStreaming.getDisplayState()) {
				this.vStreaming.setDisplayState(StageDisplayState.NORMAL);
			} else {
				this.vStreaming.setDisplayState(StageDisplayState.FULL_SCREEN);
			}
			this.vStreaming.dispatchStageEvent(new Event(Event.RESIZE));
		}

		public function onTimelineClick(e:ScrollEvent):void {
			this.stream.seek(e.porcentaje * this.stream.duration);
			this.vTimeline.setPointer(e.porcentaje),
			this.vTimeline.setText(new PercentFormater(e.porcentaje).format(this.idioma));
		}

		public function onVolumeClick(e:ScrollEvent):void {
			this.stream.volume=e.porcentaje;
			this.vVolume.setPointer(e.porcentaje);
			this.vVolume.setText(new PercentFormater(e.porcentaje).format(this.idioma));
		}

		public function onResizeEvent(e:Event):void {
			if (StageDisplayState.FULL_SCREEN==this.vStreaming.getDisplayState()) {
				this.vVideo.move(0,0);
				this.vVideo.setSize(this.properties.STAGE.width,this.properties.STAGE.height);
				this.vPortada.move(0,0);
				this.vPortada.setSize(this.properties.STAGE.width,this.properties.STAGE.height);
			} else {
				this.vVideo.move(this.properties.VIDEO.x,this.properties.VIDEO.y);
				this.vVideo.setSize(this.properties.VIDEO.width,this.properties.VIDEO.height);
				this.vPortada.move(this.portadaCropedRectangle.x, this.portadaCropedRectangle.y);
				this.vPortada.setSize(this.portadaCropedRectangle.width,this.portadaCropedRectangle.height);
			}
			this.vCargador.setPosition(new ImagenAjuste().getImagenCenter(this.vCargador.getSize(), this.vStreaming.getStageSize()));
			
		}

		private function connectedHandler():void {
			this.stream=new AkamaiEnhancedNetStream(this.connection);
			this.stream.volume=.8;

			// If the server requires us to subscribe to live this.streams, we need a few more event handlers
			//if (this.connection.subscribeRequiredForLiveStreams) {
			//this.stream.addEventListener(OvpEvent.SUBSCRIBED,subscribedHandler);
			//this.stream.addEventListener(OvpEvent.UNSUBSCRIBED,unsubscribedHandler);
			//this.stream.addEventListener(OvpEvent.SUBSCRIBE_ATTEMPT,subscribeAttemptHandler);
			//}
			this.stream.addEventListener(OvpEvent.PROGRESS,progressHandler);
			this.stream.addEventListener(NetStatusEvent.NET_STATUS,netStreamStatusHandler);
			//
			//this.stream.addEventListener(OvpEvent.NETSTREAM_PLAYSTATUS,streamPlayStatusHandler);
			//this.stream.addEventListener(OvpEvent.NETSTREAM_METADATA, this.onMetaData);
			//this.stream.addEventListener(OvpEvent.NETSTREAM_CUEPOINT, cuepointHandler);
			//this.stream.addEventListener(OvpEvent.DEBUG, debugMsgHandler);
			//this.stream.addEventListener(OvpEvent.COMPLETE,completeHandler); 
			//
			this.vVideo.attachNetStream(this.stream);
			//NIELSEN
		}
		// CONTROLADOR STREAMING

		// CARGADOR
		public function addElementos(numero:int):void {
			//this.nElementos += numero;
		}
		public function removeElementos(numero:int):void {
			//this.nElementos -= numero;
		}
		private function setCargadorInfo(porcentaje:Number, playing:Boolean):void {
			this.vCargador.setContador(new PercentFormater(porcentaje).format(this.idioma));
			this.vCargador.setProgress(porcentaje);
			this.vCargador.setVisible(!playing);
			this.vPortada.setVisible(!playing);
		}
		// CARGADOR
		// Handles NetConnection status events. The description notifier is displayed
		// for rejection events.

		private function netStatusHandler(e:NetStatusEvent):void {
			trace('netStatusHandler' + e.info.code);

			switch (e.info.code) {
				case "NetConnection.Connect.Success" :
					connectedHandler();
					this.setControlsView(AkamaiEnhancedNetStream.STATE_STOPPED);
					if (this.autoplay) {
						this.onPlayClick(new MouseEvent(MouseEvent.CLICK));
					}
					this.connection.call("checkBandwidth", null); 					
					break;
				case "NetConnection.Connect.Rejected" :
					trace("Rejected by server. Reason is " + e.info.description);
					break;
			}
		}
		private function netStreamStatusHandler(event:NetStatusEvent):void {
			switch (event.info.code) {
				case "NetStream.Play.Start" :
					trace("Start");
					this.nielsenVideoCall.initTimer(new Timer(180000,0));
					break;
				case "NetStream.Play.Stop" :
					trace("stop");
					this.nielsenVideoCall.stopTimer();
					break;
			}
		}

		// Updates the UI elements as the  video plays
		private function progressHandler(e:OvpEvent):void {
			this.setCargadorInfo(this.stream.bufferPercentage/100, this.stream.currentFPS != 0);
		}
	}
}